package bdd;

import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;

import sheepmixView.client.model.Musique;


import com.mpatric.mp3agic.*;

public class DBConnection {

	private ControleurSGBD control; 


	// Etablissement de la connexion et fermeture (au début et à la fermeture du programme)
	//========================================================================================================================================================
	
	
	/**
	 * Declaration d'un controleur SGBD
	 * @param url
	 * @param user
	 * @param password
	 */
	public DBConnection(String url, String user, String password) {
		control = new ControleurSGBD(url, user, password);
	}

	
	/**
	 * Declaration d'un controleur SGBD
	 * @param serveur
	 * @param nomBase
	 * @param noPort
	 * @param user
	 * @param pwd
	 */
	public DBConnection(String serveur, String nomBase, int noPort, String user, String pwd) {
		String url = "//" + serveur + ":" + noPort + "/" + nomBase;
		control = new ControleurSGBD(url, user, pwd);
	}
	
	/**
	 * Connection au serveur SGBD
	 */
	public void connect() {
		control.connect();
	}

	/**
	 * Deconnection du serveur SGBD
	 */
	public void disconnect() {
		control.close();
	}
	//========================================================================================================================================================


	// Utilisation de ces fonctions lors des mises à jours
	//========================================================================================================================================================
	/**
	 * Permet d'introduire de nouvelles musiques dans la base de donnee.
	 * @param addedFiles Fichiers a introduire.
	 */
	public void addFiles(LinkedList<String> addedFiles) {

		Mp3File current;
		File file;
		RequeteSQL req    = new RequeteSQL();
		String titre      = "Inconnu";
		String auteur     = "Inconnu";
		String genre      = "Inconnu";
		String album      = "Inconnu";
		String nomFichier = "Inconnu";
		int erreurs=0;

		ResultSet rs;

		for(int i = 0; i < addedFiles.size(); i++) {
			//System.out.println(files.get(i));
			try {
				file = new File(addedFiles.get(i));
				current = new Mp3File(addedFiles.get(i));

				// Stockage temporaire des tag de la musiques
				if (current.hasId3v2Tag() || current.hasId3v1Tag()) {
					ID3v2 tag  = current.getId3v2Tag();
					if(tag.getTrack() != null) {
						nomFichier = tag.getTrack();                nomFichier = nomFichier.replaceAll("\'"," ");}
					if(tag.getTitle() != null) {
						titre      = tag.getTitle();                titre = titre.replace("\'"," ");}
					if(tag.getArtist() != null) {
						auteur     = tag.getArtist();               auteur = auteur.replace("\'"," ");}
					if(tag.getGenreDescription() != null) {
						genre      = tag.getGenreDescription();     genre = genre.replace("\'"," ");}
					if(tag.getAlbum() != null) {
						album      = tag.getAlbum();                album = album.replace("\'"," ");}

				}
				

				// Ajout du genre (s'il n'existe pas)
				rs = control.executionRequete(req.existeGenre(genre));
				if(!rs.first())
					control.executionRequeteModify(req.ajouterGenre(genre));

				// Ajout de l'auteur (s'il n'existe pas)
				rs = control.executionRequete(req.existeArtiste(auteur));
				if(!rs.first())
					control.executionRequeteModify(req.ajouterArtiste(auteur));

				String chemin = file.getCanonicalPath();
				chemin = chemin.replace("\\", "\\\\");
				// Ajout de la musique
				control.executionRequeteModify(req.ajouterMp3(file.getName(),
						titre, 
						album, 
						genre, 
						chemin, 
						auteur));

			}
			catch(Exception e) {
				e.printStackTrace();
			}

		}

		System.out.println("Erreurs : " + erreurs);
	}

	/**
	 * Nettoyage de la base de donnee
	 */
	public void flushDB() {
		RequeteSQL req    = new RequeteSQL();
		control.executionRequeteModify(req.supprimerToutArtistes());
		control.executionRequeteModify(req.supprimerToutGenres());
	}

	/**
	 * Permet de supprimer une liste de musiques de la base de donnee. Si l'auteur ou le genre sont vides, ils disparaissent.
	 * @param removedFiles
	 */
	public void removeFiles(LinkedList<String> removedFiles) {
		RequeteSQL req    = new RequeteSQL();
		LinkedList<String> genreSupprimes    = new LinkedList<String>();
		LinkedList<String> artistesSupprimes = new LinkedList<String>();
		ResultSet rs;

		// On stocke les genres et les artistes qui vont perdre des tuples.
		for(int i=0; i < removedFiles.size(); i++) {
			rs = control.executionRequete(req.sortirInfoMusique(removedFiles.get(i)));
			try {
				if(rs.first()) {
					if(!genreSupprimes.contains(rs.getNString("GENRE"))) {
						genreSupprimes.add(rs.getNString("GENRE"));
					}
					if(!artistesSupprimes.contains(rs.getNString("ARTISTE"))) {
						artistesSupprimes.add(rs.getNString("ARTISTE"));
					}
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}

			control.executionRequeteModify(req.supprimerMp3(removedFiles.get(i)));
		}

		// On regarde si les genres et les artistes modifiés contiennent encore des musiques.
		for(int i = 0; i < genreSupprimes.size(); i++) {
			rs = control.executionRequete(req.sortirMusiqueGenre(genreSupprimes.get(i)));
			try {
				if(!rs.first())
					control.executionRequeteModify(req.supprimerGenre(genreSupprimes.get(i)));
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		for(int i = 0; i < artistesSupprimes.size(); i++) {
			rs = control.executionRequete(req.sortirMusiqueArtiste(artistesSupprimes.get(i)));
			try {
				if(!rs.first())
					control.executionRequeteModify(req.supprimerArtiste(artistesSupprimes.get(i)));
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	//========================================================================================================================================================

	
	// Fonction pour creer des playlists
	//========================================================================================================================================================

	/**
	 * Recuperer dans une liste toutes les musiques de la base de donnee.
	 * @return
	 */
	public LinkedList<Musique> getDatabaseTracks() {
		LinkedList<Musique> list = new LinkedList<Musique>();
		RequeteSQL req    = new RequeteSQL();
		ResultSet  rs;
		rs = control.executionRequete(req.sortirToutesLesMusiques());
		try {
			while(rs.next()) {
				list.add(new Musique(rs.getInt("ID"),rs.getNString("TITRE"),rs.getNString("ARTISTE"),rs.getNString("ALBUM"),rs.getNString("CHEMIN")));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;
	}
	
	public String getPathTrack(int id) {
		RequeteSQL req    = new RequeteSQL();
		ResultSet  rs;
		rs = control.executionRequete(req.sortirChemin(id));
		try {
			if(rs.first())
				return rs.getNString("CHEMIN");
			else
				return null;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * Recuperer dans une liste toutes les musiques d'un certain artiste.
	 * @param artist
	 * @return
	 */
	public LinkedList<Musique> getArtistTracks(String artist) {
		LinkedList<Musique> list = new LinkedList<Musique>();
		RequeteSQL req    = new RequeteSQL();
		ResultSet  rs;
		rs = control.executionRequete(req.sortirMusiqueArtiste(artist));
		try {
			while(rs.next()) {
				list.add(new Musique(rs.getInt("ID"),rs.getNString("TITRE"),rs.getNString("ARTISTE"),rs.getNString("ALBUM"),rs.getNString("CHEMIN")));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;
	}
	
	/**
	 * Recuperer dans une liste toutes les musiques d'un certain genre.
	 * @param genre
	 * @return
	 */
	public LinkedList<Musique> getGenreTracks(String genre) {
		LinkedList<Musique> list = new LinkedList<Musique>();
		RequeteSQL req    = new RequeteSQL();
		ResultSet  rs;
		rs = control.executionRequete(req.sortirMusiqueGenre(genre));
		try {
			while(rs.next()) {
				list.add(new Musique(rs.getInt("ID"),rs.getNString("TITRE"),rs.getNString("ARTISTE"),rs.getNString("ALBUM"),rs.getNString("CHEMIN")));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;
	}
	
	/**
	 * Recuperer un titre particulier d'un artiste particulier.
	 * @param title
	 * @param author
	 * @return
	 */
	public Musique getTrack(String title, String author) {
		RequeteSQL req    = new RequeteSQL();
		ResultSet rs;
		rs = control.executionRequete(req.sortirTitreParticulier(title, author));
		try {
			if(rs.first())
				return new Musique(rs.getInt("ID"),rs.getNString("TITRE"),rs.getNString("ARTISTE"),rs.getNString("ALBUM"),rs.getNString("CHEMIN"));
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	public Musique getTrack(int id) {
		RequeteSQL req    = new RequeteSQL();
		ResultSet rs;
		rs = control.executionRequete(req.sortirTitreParticulier(id));
		try {
			if(rs.first())
				return new Musique(rs.getInt("ID"),rs.getNString("TITRE"),rs.getNString("ARTISTE"),rs.getNString("ALBUM"),rs.getNString("CHEMIN"));
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Obtenir sous forme de liste de 'String' les genres presents dans la base.
	 * @return
	 */
	public LinkedList<String> getGenreList() {
		RequeteSQL req    = new RequeteSQL();
		ResultSet rs;
		LinkedList<String> list = new LinkedList<String>(); 
		rs = control.executionRequete(req.sortirTousLesGenres());
		try {
			while(rs.next()) {
				list.add(rs.getNString("NOM_GENRE"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * Obtenir sous forme de liste de 'String' les artistes presents dans la base.
	 * @return
	 */
	public LinkedList<String> getArtistList() {

		RequeteSQL req    = new RequeteSQL();
		ResultSet rs;
		LinkedList<String> list = new LinkedList<String>(); 
		rs = control.executionRequete(req.sortirToutLesArtistes());
		try {
			while(rs.next()) {
				list.add(rs.getNString("NOM_ARTISTE"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;

	}

	/**
	 * Obtenir la liste des artistes d'un certain genre.
	 * @param genre
	 * @return
	 */
	public LinkedList<String> getArtistList(String genre) {

		RequeteSQL req    = new RequeteSQL();
		ResultSet rs;
		LinkedList<String> list = new LinkedList<String>(); 
		rs = control.executionRequete(req.sortirArtisteGenre(genre));
		try {
			while(rs.next()) {
				list.add(rs.getNString("ARTISTE"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;

	}
	
	//=========================================================================================================================================================


	// 
	//========================================================================================================================================================
	// Cette fonction sera implémentée plus tard, mais elle nécéssite qu'un controle
	// des requêtes afin d'éviter d'évetuelles attaques par injections.
	public LinkedList<String> databaseResearch(String search) {
		
		return null;
	}

	public String secureSQL(String userEntry){
		
		return null;
	}

}

